<?php
class Backend_Page_Controller extends Backend_Controller_Crud_Vc
{

    public function indexAction()
    {
        parent::indexAction();
        
        $resource = Resource::getInstance();     
        $resource->addJs('/js/app/system/BlocksPanel.js' , 3); 
        
        $fModules = Config::factory(Config::File_Array, $this->_configMain->get('frontend_modules'));        
        $funcList = array(
        	array('id'=>'','title'=>'---')
        );    
           
        foreach ($fModules as $code=>$config)
        	$funcList[] = array('id'=>$code  , 'title'=>$config['title']);
        
        $resource->addInlineJs('
        	var aFuncCodes = '.json_encode($funcList).';
        ');
    }
    
    /**
     * Get list of pages as a data tree config
     * @todo take rv config from liasAtion
     */
    public function treelistAction()
    {
         $pagesModel = Model_Page::getInstance();
         Response::jsonArray($pagesModel->getTreeList( array( 'id','parent_id','published','code')));
    }
    /**
     * Get pages as array
     * 
     */
    public function listAction()
    {
          $pageModel = Model_Page::getInstance();
          $data = $pageModel->getListVc(
          	  array('sort'=>'order_no','dir'=>'ASC'), 
          	  false, 
          	  false,
              array(
                  'id',
                  'parent_id',
                  'menu_title',
                  'published',
                  'code' ,
                  'date_updated',
                  'date_created',
                  'published_version'
              )
              ,'user', 'updater'
         );  
          
         if(empty($data))
            Response::jsonSuccess(array()); 
          
         $ids = Utils::fetchCol('id', $data);
         $maxRevisions = Model_Vc::getInstance()->getLastVersion('page',$ids);
            
         foreach ($data as $k=>&$v)
         {
             if(isset($maxRevisions[$v['id']]))
                  $v['last_version'] = $maxRevisions[$v['id']];
             else
                  $v['last_version'] = 0;   
         }
         unset($v);    
         Response::jsonSuccess($data);
    }
    
    /**
     * Get blocks
     */
    public function blocklistAction()
    {
         $blocksModel = Model_Blocks::getInstance();
         $data = $blocksModel->getListVc(false,false,false,array('id','title','is_system','published'));

         foreach ($data as $k=>&$v)
         	$v['deleted'] = false;
      
         Response::jsonSuccess($data);
    }
    
    /**
     * Check if page code is unique
     */
    public function checkCodeAction()
    {
        $id = Request::post('id', 'int', 0);
        $code = Request::post('code','string',false);    
        $code = Filter::filterValue('pagecode', $code);
        
        $model = Model_Page::getInstance();
        
        if($model->checkUnique($id , 'code' , $code))
            Response::jsonSuccess(array('code'=>$code));
        else 
            Response::jsonError($this->_lang->SB_UNIQUE);    
    }
    /**
     * Change page sorting action
     */
    public function sortpagesAction()
    { 
       $id = Request::post('id','integer',false);
       $newParent = Request::post('newparent','integer',false);
       $order = Request::post('order', 'array' , array());

       $this->_checkCanEdit();
       
       if(!$id || !strlen($newParent) || empty($order))
            Response::jsonError($this->_lang->WRONG_REQUEST);     
                       
       try{                
           $pObject = new Db_Object('page' , $id);
           $pObject->set('parent_id', $newParent);  
           $pObject->save();
           Model_Page::getInstance()->updateSortOrder($order);
           Response::jsonSuccess();
        } catch (Exception $e){
           Response::jsonError($this->_lang->CANT_EXEC);
        }
    }
	
    public function createAction()
    {
       if(!User_Admin::getInstance()->canEdit($this->_module))
          Response::jsonError($this->_lang->CANT_MODIFY);
    
       self::insertObject(self::getPostedData($this->_module));
    }

    public function updateAction()
    { 
       if(!User_Admin::getInstance()->canEdit($this->_module))
          Response::jsonError($this->_lang->CANT_MODIFY);
        
       self::updateObject(self::getPostedData($this->_module)); 
    }
    
    static public function getPostedData($objectName)
    {
       /*
        * Init lang object (it is static method)
        */ 
       $lang = Lang::getInstance(); 
       $id = Request::post('id','integer',0);
       
       if($id)
       {
            try {
            	$obj = new Db_Object($objectName, $id);
            }catch (Exception $e){
                Response::jsonError($lang->CANT_EXEC);
            }
        }
        else
        { 
            $obj = new Db_Object($objectName);          
            if($obj->getConfig()->isRevControl())
            	$obj->set('published' , false);
        }
        
        $posted = Request::postArray();
        
        $fields= $obj->getFields();
        $errors = array(); 
        
        $posted['user_id'] = User::getInstance()->id;
        $posted['date'] = date('Y-m-d H:i:s');
        
        $uniqGroups = array();
        foreach ($fields as $name)
        {
           if($obj->getConfig()->isRequired($name) && (!isset($posted[$name]) || !strlen($posted[$name]))){
                $errors[$name] = $lang->CANT_BE_EMPTY;
                continue;
           }

           if($obj->getConfig()->isBoolean($name) && !isset($posted[$name]))
                $posted[$name] = false;
                                                  
           if(!array_key_exists($name, $posted))
                continue;

           if($name=='blocks' && isset($posted[$name])){
                if(is_array($posted[$name]))
                    $posted[$name] = serialize($posted[$name]);
                else
                    $posted[$name] = serialize(array());
           }           
           try{
                $obj->set($name,  $posted[$name]);
           }catch (Exception $e){
               $errors[$name] = $lang->INVALID_VALUE;
           }
                
        }   
        
        if(!empty($errors))
             Response::jsonError($lang->FILL_FORM , $errors);
        
        $errors = $obj->validateUniqueValues();

        if(!empty($errors))
          Response::jsonError($lang->FILL_FORM , $errors);
             
        if($id)       
           $obj->setId($id);
    
        return $obj;        
    }
    
	/**
     * Read object action
     */
    public function loaddataAction()
    {
        $id = Request::post('id', 'integer', false);
        $version = Request::post('version','integer',0);
 
        if(!$id)
            Response::jsonSuccess(array());
        
        $vc = Model_Vc::getInstance();
        
        try{
            $obj = new Db_Object($this->_module, $id);
        }catch(Exception $e){
            Response::jsonError($this->_lang->CANT_EXEC);
        }
               
        if(!$version)     
             $version = $vc->getLastVersion($this->_module, $id);     
          
        if(!$version){
              $data = $obj->getData();
              $data['id'] = $obj->getId(); 
              Response::jsonSuccess($data);
        }
              
        $data = $vc->getData($this->_module, $id , $version);
          
        if(empty($data))
            Response::jsonError($this->_lang->CANT_LOAD);
            
        $data['id'] = $id; 
        $data['version'] = $version;
        $data['published'] = $obj->get('published');
        $data['staging_url'] = Request::url(array($data['code'])).'?preview=' . $data['version'];
          
        /*
         * Prepare  mltilink properties
         */
        $fields = $obj->getFields();
        foreach($fields as $field){
            if(empty($data[$field]))
                continue;
            $linkObject = $obj->getLinkedObject($field);
            if($linkObject !== false)
                $data[$field] = array_values($this->_collectLinksData($data[$field] ,$linkObject));
        } 
        
        $theme = 'default';
        
        if(file_exists($this->_configMain->get('themes').$obj->get('theme').'/layout_cfg.php'))
            $theme = $obj->get('theme'); 
        
    	try{
    	    $config = Config::factory(Config::File_Array , $this->_configMain->get('themes') . $theme . '/layout_cfg.php');
    	}catch (Exception $e){
    		Response::jsonError($this->_lang->WRONG_REQUEST);
    	}    
        
    	$conf = $config->__toArray();
    	$items = array();
    	
    	if(isset($conf['items']) && !empty($config['items'])){
    	    foreach ($conf['items'] as $k=>$v){
    	        $v['code'] = $k;
    	        $items[] =$v;
    	    }
    	    $conf['items'] = $items;
    	}
        
        /*
         * Collect blocks info
         */
        if(!empty($data['blocks'])){
            $blocksCfg = unserialize($data['blocks']);
            foreach ($blocksCfg as $key=>&$value){
               $value = array_values($this->_collectBlockLinksData($value));
            }unset($value);   
            $data['blocks'] =array('config'=>$conf,'blocks'=>$blocksCfg);
        }else{
            $data['blocks'] = array('config'=>$conf,'blocks'=>array());
        }
        /*
         * Send response
         */
        Response::jsonSuccess($data);
    }
    
    public function blockconfigAction()
    { 
        $theme = Request::post('theme', 'string', 'default');
 
    	try{
    	    $config = Config::factory(Config::File_Array , $this->_configMain->get('themes') . $theme . '/layout_cfg.php');
    	}catch (Exception $e){
    		Response::jsonError($this->_lang->WRONG_REQUEST);
    	}    
    		
    	$conf = $config->__toArray();
    	$items = array();
    	
    	if(isset($conf['items']) && !empty($config['items']))
    	{
    	    foreach ($conf['items'] as $k=>$v){
    	        $v['code'] = $k;
    	        $items[] =$v;
    	    }
    	    $conf['items'] = $items;
    	}
    	
    	Response::jsonSuccess($conf);
    }
	/**
     * Prepear data for linked field component
     * @param array $data
     * @param string $objectName
     * @return array
     */
    protected function _collectBlockLinksData(array $data )
    {
             
        $ids = Utils::fetchCol('id', $data);
        $data =  Utils::rekey('id', $data);

        $obj = new Db_Object('Blocks');
        $model = Model_Blocks::getInstance();
        
        $fields = array('id' , 'title'=>$obj->getConfig()->getLinkTitle(),'is_system');
        $usedRC = $obj->getConfig()->isRevControl();
        if($usedRC)
            $fields[] = 'published';
        
        $odata = $model->getItems($ids , $fields);  
        if(!empty($data))
            $odata = Utils::rekey('id', $odata);
        /*
         * Find out deleted records
         */ 
        $deleted = array_diff($ids, array_keys($odata));  
        
        $deletedData = array();

        $result = array();
        foreach ($ids as $id)
        {
            if(in_array($id, $deleted)){
                 $item = array('id'=>$id , 'deleted'=>1 , 'title'=>$data[$id]['title'], 'published'=>1,'is_system'=>$data[$id]['is_system']);
                 if($usedRC)
                     $item['published'] = 0;
            } else{
                $item = array('id'=>$id , 'deleted'=>0 , 'title'=>$odata[$id]['title'],'published'=>1,'is_system'=>$data[$id]['is_system']);
                if($usedRC){
                     $item['published'] = $odata[$id]['published'];     
                 }
            }
            $result[] = $item;
        }  
        return $result;  
    }
    
    public function publishAction()
    {
        $id = Request::post('id','integer', false);
        $vers = Request::post('vers' , 'integer' , false);
        
        if(!$id || !$vers)
            Response::jsonError($this->_lang->WRONG_REQUEST);
        
        if(!User_Admin::getInstance()->canPublish($this->_module))
             Response::jsonError($this->_lang->CANT_PUBLISH);

        try{
            $object = new Db_Object($this->_module , $id);  
        }catch(Exception $e){
            Response::jsonError($this->_lang->CANT_EXEC);
        }        
        
        $vc= Model_Vc::getInstance();
        
        $data = $vc->getData($this->_module , $id , $vers);       
        
        /*
         * Do not publish some data
         * parent_id and order_no can be changed outside of version control
         */
        $publishException = array('id' , 'order_no' , 'parent_id');
        foreach ($publishException as $field)
        	if(array_key_exists($field, $data))
        		unset($data[$field]);
 		
        if(empty($data))
            Response::jsonError($this->_lang->CANT_EXEC);
            
         foreach ($data as $k=>$v)
         {
             if($object->fieldExists($k))
             {
                 if($object->getConfig()->isMultiLink($k) && !empty($v))
                     $v = array_keys($v);         
                 try{
                     $object->set($k , $v);
                 }catch (Exception $e){
                     Response::jsonError($this->_lang->VERSION_INCOPATIBLE);
                 }
             } 
         }   
             
         if(isset($data['blocks']) && strlen($data['blocks'])){
             $blocks = unserialize($data['blocks']);
             if(empty($blocks))
                 $blocks = array();
                 
             if(!Model_Blocks::getInstance()->setMapping($id , $blocks))
                 Response::jsonError($this->_lang->CANT_EXEC.' code 2');
         }

        $object->set('published_version' , $vers);
        $object->set('published', true); 
             
        if(!$object->save(false))
            Response::jsonError($this->_lang->CANT_EXEC);
   
         $hl = Model_Historylog::getInstance();
         $hl->log(
                          User_Admin::getInstance()->id,
                          $object->getId(),
                          Model_Historylog::Publish ,
                          $object->getTable()
                 );   
        Response::jsonSuccess();
    }
    /**
     * (non-PHPdoc)
     * @see Backend_Controller_Crud::deleteAction()
     */
    public function deleteAction(){
    
        if(!User_Admin::getInstance()->canDelete($this->_module))
            Response::jsonError($this->_lang->CANT_DELETE);
            
        $id = Request::post('id','integer', false);
            
        try{
        	$object = new Db_Object($this->_module , $id);
        }catch(Exception $e){
        	Response::jsonError($this->_lang->WRONG_REQUEST);
        }
    
         if(!$id)
            Response::jsonError($this->_lang->WRONG_REQUEST);
            
          
         if($this->_configMain->get('vc_clear_on_delete'))
             Model_Vc::getInstance()->removeItemVc($this->_module , $id);
             
         if(!$object->delete())
             Response::jsonError($this->_lang->CANT_EXEC);
             
         Model_Blockmapping::getInstance()->clearMap($id);   
         Response::jsonSuccess();
    }
    /**
     * Get themes list
     */
    public function themeslistAction()
    {
        $themes = File::scanFiles($this->_configMain->get('themes'),false,false, File::Dirs_Only);
        $result = array();
        if(!empty($themes))
        {
            foreach ($themes as $name){
                $code = basename($name);
                if($code[0]!='.')
                	$result[] = array('id'=>$code,'title'=>$code);
            }    
        }
        Response::jsonSuccess($result);
    }
}